package com.laysonx.data.police.core;

import com.laysonx.data.police.exception.DataVerifyRuleException;
import com.laysonx.data.police.handler.DataHandler;
import com.laysonx.data.police.handler.DisposeHandler;
import com.laysonx.data.police.handler.VerifyHandler;
import org.aopalliance.aop.Advice;
import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 装配数据清理、数据验证处理器
 *
 * @author: Laysonx
 * @date: 2019/9/27 15:51
 */
public class DataVerifyInfoConfigurerProcessor implements BeanPostProcessor, ApplicationContextAware {

    private static ApplicationContext context = null;

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        if (bean instanceof DataVerifyInfoConfigurer) {
            // 从容器中获取 DataVerifyInfoChecker
            DataVerifyInfoChecker infoChecker = context.getBean(DataVerifyInfoChecker.class);

            // 加载 verifyHandler
            Map<Class<?>, Map<String, VerifyHandler>> verifyHelper = this.loadVerifyHandler();
            // 加载 dataHandler
            Map<Class<?>, Map<String, DataHandler>> dataHelper = this.loadDataHandler();
            // 加载 disposeHandler
            Map<Class<?>, Map<String, DisposeHandler>> disposeHelper = this.loadDisposeHandler();

            //装配用户自定义 Helper 到 DataVerifyInfoChecker
            infoChecker.setVerifyHelper(verifyHelper);
            infoChecker.setDataHelper(dataHelper);
            infoChecker.setDisposeHelper(disposeHelper);
            ((DataVerifyInfoConfigurer) bean).setInfoChecker(infoChecker);

            // 获取数据检查切面
            AspectJExpressionPointcutAdvisor advisor = context.getBean(AspectJExpressionPointcutAdvisor.class);
            // 替换 advice
            advisor.setAdvice((Advice) bean);
        }
        return bean;
    }

    /**
     * 加载 DisposeHandler
     * @author: laysonx
     * @date: 2019/11/5 10:22
     * @param
     * @return: java.util.Map<java.lang.Class<?>,java.util.Map<java.lang.String,com.laysonx.data.police.handler.DisposeHandler>>
     */
    private Map<Class<?>, Map<String, DisposeHandler>> loadDisposeHandler() {
        // 从容器中获取用户自定义的 disposeHandler 子类
        Map<String, DisposeHandler> disposeHandlerMap = context.getBeansOfType(DisposeHandler.class);
        // 组装 disposeHelper 用于数据校验后的处理方式
        Map<Class<?>, Map<String, DisposeHandler>> disposeHelper = new HashMap<>(disposeHandlerMap.size());
        for (DisposeHandler handler : disposeHandlerMap.values()) {
            Class targetClass = handler.getTargetClass();
            String tag = handler.getTag();
            if (Objects.isNull(targetClass)) {
                throw new DataVerifyRuleException(handler.getClass().getName() + "实现getTargetClass()方法返回值无意义：return null");
            }
            Map<String, DisposeHandler> tagDisposeHandlerMap = new HashMap<>(disposeHandlerMap.size());
            if (disposeHelper.containsKey(targetClass)) {
                tagDisposeHandlerMap = disposeHelper.get(targetClass);
                if(tagDisposeHandlerMap.containsKey(tag)){
                    throw new DataVerifyRuleException("DisposeHandler组装异常：targetClass=" + targetClass + ",tag=" + tag + "对应多个DisposeHandler");
                }
            }
            tagDisposeHandlerMap.put(tag,handler);
            disposeHelper.put(targetClass, tagDisposeHandlerMap);
        }
        return disposeHelper;
    }

    /**
     * 加载 DataHandler
     * @author: laysonx
     * @date: 2019/11/5 10:22
     * @param
     * @return: java.util.Map<java.lang.Class<?>,java.util.Map<java.lang.String,com.laysonx.data.police.handler.DataHandler>>
     */
    private Map<Class<?>, Map<String, DataHandler>> loadDataHandler() {
        // 从容器中获取用户自定义的 DataHandler 子类
        Map<String, DataHandler> dataHandlerMap = context.getBeansOfType(DataHandler.class);
        // 组装 dataHelper 用于数据清洗
        Map<Class<?>, Map<String, DataHandler>> dataHelper = new HashMap<>(dataHandlerMap.size());
        for (DataHandler handler : dataHandlerMap.values()) {
            Class targetClass = handler.getTargetClass();
            String tag = handler.getTag();
            if (Objects.isNull(targetClass)) {
                throw new DataVerifyRuleException(handler.getClass().getName() + "实现getTargetClass()方法返回值无意义：return null");
            }

            Map<String, DataHandler> tagDataHandlerMap = new HashMap<>(dataHandlerMap.size());
            if (dataHelper.containsKey(targetClass)) {
                tagDataHandlerMap = dataHelper.get(targetClass);
                if(tagDataHandlerMap.containsKey(tag)){
                    throw new DataVerifyRuleException("DataHelper组装异常：targetClass=" + targetClass + ",tag=" + tag + "对应多个DataHandler");
                }
            }
            tagDataHandlerMap.put(tag,handler);
            dataHelper.put(targetClass, tagDataHandlerMap);
        }
        return dataHelper;
    }

    /**
     * 加载 VerifyHandler
     * @author: laysonx
     * @date: 2019/11/5 10:22
     * @param
     * @return: java.util.Map<java.lang.Class<?>,java.util.Map<java.lang.String,com.laysonx.data.police.handler.VerifyHandler>>
     */
    private Map<Class<?>, Map<String, VerifyHandler>> loadVerifyHandler() {
        // 从容器中获取用户自定义的 VerifyHandler 子类
        Map<String, VerifyHandler> verifyHandlerMap = context.getBeansOfType(VerifyHandler.class);
        // 组装 verifyHelper 用于数据校验
        Map<Class<?>, Map<String, VerifyHandler>> verifyHelper = new HashMap<>(verifyHandlerMap.size());
        for (VerifyHandler handler : verifyHandlerMap.values()) {
            Class targetClass = handler.getTargetClass();
            String tag = handler.getTag();
            if (Objects.isNull(targetClass)) {
                throw new DataVerifyRuleException(handler.getClass().getName() + "实现getTargetClass()方法返回值无意义：return null");
            }

            Map<String, VerifyHandler> tagVerifyHandlerMap = new HashMap<>(verifyHandlerMap.size());
            if (verifyHelper.containsKey(targetClass)) {
                tagVerifyHandlerMap = verifyHelper.get(targetClass);
                if(tagVerifyHandlerMap.containsKey(tag)){
                    throw new DataVerifyRuleException("VerifyHelper组装异常：targetClass=" + targetClass + ",tag=" + tag + "对应多个VerifyHandler");
                }
            }
            tagVerifyHandlerMap.put(tag,handler);
            verifyHelper.put(targetClass, tagVerifyHandlerMap);
        }
        return verifyHelper;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}
